import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:flame/components.dart' hide Timer;
import 'package:flame/effects.dart';
import 'package:flame/events.dart';
import 'package:flame/flame.dart';
import 'package:flame/particles.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flutter/material.dart';
import 'package:freedom/const/game_const.dart';
import 'package:freedom/entity/restful.dart';
import 'package:freedom/page/mahjong/common/mahjong_context.dart';
import 'package:freedom/page/mahjong/common/message_content.dart';
import 'package:freedom/page/mahjong/event/user_reflash_action.dart';
import 'package:freedom/page/mahjong/mahjong_game.dart';
import 'package:freedom/page/mahjong/message/action_message.dart';
import 'package:freedom/util/api_router.dart';
import 'package:freedom/util/http.dart';

class GamingActionComponent extends PositionComponent
    with HasGameRef<MahjongIndexGame> {
  GamingActionComponent()
      : super(
            size: MahjongContext().bottomGamingActionAreaSize,
            position: MahjongContext().bottomGamingActionAreaPoint);
  final Random _random = Random();

  Vector2 randomVector() {
    Vector2 base = Vector2.random(_random); //  (0, 0) ~ (1, 1)
    Vector2 fix = Vector2(-0.5, -0.5);
    base = base + fix; //  (-0.5, -0.5) ~ (0.5, 0.5)
    return base * 200;
    // Vector2 base = Vector2.random(_random); //  (0, 0) ~ (1, 1)
    // Vector2 fix = Vector2(-0.5,0);
    // base = base + fix; // (-0.5, 0) ~ (0.5, 1)
    // return base * 200;
  }

  Color getRandomColor() {
    Random random = Random();
    return Color.fromARGB(
      255,
      random.nextInt(256),
      random.nextInt(256),
      random.nextInt(256),
    );
  }

  void createParticle(Vector2 position) {
    // 创建 Particle 对象
    Particle particle = Particle.generate(
      count: 50,
      lifespan: 3,
      generator: (i) => AcceleratedParticle(
          child: CircleParticle(
            radius: 2,
            paint: Paint()..color = getRandomColor(),
          ),
          acceleration: randomVector(),
          speed: randomVector(),
          position: position / 2),
    );

    final ParticleSystemComponent psc =
        ParticleSystemComponent(particle: particle, position: position);
    add(psc);
  }

  @override
  FutureOr<void> onLoad() {
    MahjongContext.registerUserFunc<UserReflashActionEvent>(
        MahjongContext.currentUser!.userId, (event) {
      initAction(event.actions);
    });
  }

  @override
  double angle = 0;
  double radius = 100;

  @override
  void update(double t) {
    angle += 0.1;
  }

  void cleanCompont() {
    Set<dynamic> tempSet = Set.from(children);
    for (var item in tempSet) {
      if (item is! FlameBlocListener) item.removeFromParent();
    }
  }

  void initAction(List<String>? actions) {
    cleanCompont();
    if (actions == null || actions.isEmpty) {
      return;
    }
    actions = actions.where((String item) {
      return MahjongContext.actionImageCode.contains(item);
    }).toList();
    // 当结算状态的时候 界面已经显示了 下一把 没必要再显示准备了
    if (MahjongContext.mahjongGameIndex.gameInfo?.status == 4 &&
        actions.length == 1 &&
        actions[0] == MessageAction.PREPARE) {
      return;
    }
    var position = Vector2(size.x - size.y / 2, size.y / 2);
    for (int i = actions.length - 1, j = 0; i >= j; i--) {
      var userAction = UserActionPosition(position, actions[i], (code) {
        // 清理
        initAction([]);
      });
      add(userAction);
      position.x -= MahjongContext().bottomGamingActionSize.x * 1.3;
    }
  }

  @override
  void render(Canvas canvas) {}
}

class UserActionPosition extends PositionComponent with TapCallbacks, HasPaint {
  String code;
  List<double> range = [];
  int index = 0;
  double radius = 0.0;
  bool _due = true;

  Function success;

  var lastSize = MahjongContext().bottomGamingActionSize;

  UserActionPosition(Vector2 position, this.code, this.success)
      : super(size: Vector2.all(0), position: position, anchor: Anchor.center);

  @override
  FutureOr<void> onLoad() async {
    add(SizeEffect.by(
      lastSize,
      EffectController(duration: 0.3),
    ));
    var defaultSize = lastSize.x / 2 * 0.8;
    range.add(defaultSize);
    range.add(defaultSize + 5);
    range.add(defaultSize + 10);
    radius = range[0];
    Timer.periodic(const Duration(milliseconds: 500), (timer) {
      if (_due) {
        index++;
      } else {
        index--;
      }
      if (index >= range.length - 1) {
        _due = false;
      } else if (index <= 0) {
        _due = true;
      }
    });
  }

  @override
  void onTapDown(TapDownEvent event) {
    // 争对杠  单独处理
    if (code == ActionMessageHandler.BAR) {
      List<int> allBarCard = MahjongContext.currentUser?.allBarCard() ?? [];
      if (allBarCard.isNotEmpty && allBarCard.length >= 2) {
        MahjongContext.mahjongGameIndex
            .setMultiCard(ActionMessageHandler.BAR, allBarCard);
        MahjongContext().showOverlay(MahjongOverlay.multipmleChoiceCardDialog);
        return;
      }
    }

    var data = MessageContent<List<MahjongMessage>>(
        type: MessageContent.MT_ACT,
        body: [MahjongMessage(type: code)]).toJson();
    Http.getInstance().request<Restful>(ApiRouter.roomMessage,
        contentType: ContentType.json,
        type: RequestEnum.POST,
        showErrorMsg: true,
        data: data, success: (data) {
      success(code);
    });
  }

  @override
  bool containsLocalPoint(Vector2 point) {
    Rect rect = Rect.fromLTWH(0, 0, size.x, size.y);
    return rect.contains(Offset(point.x, point.y));
  }

  @override
  void render(Canvas canvas) {
    var barAction = Flame.images.fromCache('mahjong/action/$code.png');
    Sprite(barAction).render(canvas, size: size, position: Vector2.all(0.0));
    Offset center = Offset(width / 2, width / 2);
    RadialGradient gradient = const RadialGradient(
      colors: [Color.fromARGB(0, 249, 253, 4), Color.fromARGB(200, 255, 0, 0)],
      stops: [0.4, 1.0],
      center: Alignment.center,
      radius: 1.0,
    );
    for (int i = 0; i <= index; i++) {
      final paint = Paint()
        ..strokeWidth = 2
        ..shader = gradient
            .createShader(Rect.fromCircle(center: center, radius: range[i]));
      canvas.drawCircle(center, range[i], paint);
    }
  }

  @override
  void update(double dt) {
    super.update(dt);
  }
}
